// Copyright(c) 2011 Matthew McMullan, Jorel Lalicki and Mike Heise, Jorel Lalicki and Mike Heise. See copying.txt for details.

#ifndef __agml_x86_h__
#define __agml_x86_h__

// make sure that this file is never included directly
#ifndef __agml_agml_h__
#error "Include AGML from agml.h only. This file is not a valid entry point for the library."
#endif

// detect processor features
#ifdef __agml_compiler_gcc_compat
//fixme: messy gcc errors when not enough are enabled
#ifdef __3dNOW__
#define __agml_x86_3dn
#endif
#ifdef __ABM__
#define __agml_x86_abm
#endif
#ifdef __AES__
#define __agml_x86_aes
#endif
#ifdef __AVX__
#define __agml_x86_avx
#endif
#ifdef __FMA4__
#define __agml_x86_fma4
#endif
// __agml_x86_general not supported in any GCC setting
#ifdef __LWP__
#define __agml_x86_lwp
#endif
#ifdef __MMX__
#define __agml_x86_mmx
#endif
#ifdef __PCLMUL__
#define __agml_x86_clmul
#endif
#ifdef __POPCNT__
#define __agml_x86_popcnt
#endif
#ifdef __RDRND__
#define __agml_x86_rdrnd
#endif
#ifdef __SSE__
#define __agml_x86_sse
#endif
#ifdef __SSE2__
#define __agml_x86_sse2
#endif
#ifdef __SSE3__
#define __agml_x86_sse3
#endif
#ifdef __SSSE3__
#define __agml_x86_ssse3
#endif
#ifdef __SSE4_1__
#define __agml_x86_sse41
#endif
#ifdef __SSE4_2__
#define __agml_x86_sse42
#endif
#ifdef __SSE4A__
#define __agml_x86_sse4a
#endif
#ifdef __XOP__
#define __agml_x86_xop
#endif

#elif defined __agml_compiler_msvcc

#ifdef _M_CEE_PURE
#warning "Compiling in pure mode. All intrinsics will be disabled"
#undef __agml_arch_x86
#undef __agml_arch_x86_32
#undef __agml_arch_x86_64
#define __agml_arch_other
#else
#define __agml_x86_3dn
#define __agml_x86_abm
#define __agml_x86_aes
#define __agml_x86_avx
#define __agml_x86_fma4
#define __agml_x86_general
#define __agml_x86_lwp
#define __agml_x86_mmx
#define __agml_x86_clmul
#define __agml_x86_popcnt
#define __agml_x86_rdrnd
#define __agml_x86_sse
#define __agml_x86_sse2
#define __agml_x86_sse3
#define __agml_x86_ssse3
#define __agml_x86_sse41
#define __agml_x86_sse42
#define __agml_x86_sse4a
#define __agml_x86_xop
#endif

#else
#warning "This compiler does not have known intrinsic support: falling back on generic implementation"
#undef __agml_arch_x86
#undef __agml_arch_x86_32
#undef __agml_arch_x86_64
#define __agml_arch_other
#endif

// simd compiler intrinsics
// GCC
#ifdef __agml_compiler_gcc_compat
// MMX
#ifdef __agml_x86_mmx
#include <mmintrin.h>
#endif
// 3DNow!
#ifdef __agml_x86_3dn
#include <mm3dnow.h>
#endif
// SSE
#ifdef __agml_x86_sse
#include <xmmintrin.h>
#endif
// SSE2
#ifdef __agml_x86_sse2
#include <emmintrin.h>
#endif
// SSE3
#ifdef __agml_x86_sse3
#include <pmmintrin.h>
#endif
// SSE4.1
#ifdef __agml_x86_sse41
#include <pmmintrin.h>
#endif
// SSE4.2
#ifdef __agml_x86_sse42
#include <pmmintrin.h>
#endif
// SSE4A
#ifdef __agml_x86_sse4a
#include <pmmintrin.h>
#endif

// Visual C++
#elif defined __agml_compiler_msvcc
#include <intrin.h>
#endif

// special bulk-data types
#ifdef __agml_arch_x86
#include "v128-x86.h"
#include "v256-x86.h"
#include "v512-x86.h"
// fallback in case this compiler doesn't have known intrinsic support
#else
#include "../generic/generic.h"
#endif
#endif
